﻿/*
 * Copyright (c) 1995 The Regents of the University of California.
 * All rights reserved.    
 *
 * Permission to use, copy, modify, and distribute this software and its
 * documentation for any purpose, without fee, and without written agreement is
 * hereby granted, provided that the above copyright notice and the following
 * two paragraphs appear in all copies of this software.
 *
 * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
 * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
 * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
 * CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
 * AND FITNESS FOR A PARTICULAR PURPOSE.    THE SOFTWARE PROVIDED HEREUNDER IS
 * ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO
 * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
 */

/*
 * Portions of this software Copyright (c) 1995 Brown University.
 * All rights reserved.
 * 
 * Permission to use, copy, modify, and distribute this software and its
 * documentation for any purpose, without fee, and without written agreement
 * is hereby granted, provided that the above copyright notice and the
 * following two paragraphs appear in all copies of this software.
 * 
 * IN NO EVENT SHALL BROWN UNIVERSITY BE LIABLE TO ANY PARTY FOR
 * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
 * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF BROWN
 * UNIVERSITY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 * 
 * BROWN UNIVERSITY SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
 * PARTICULAR PURPOSE.    THE SOFTWARE PROVIDED HEREUNDER IS ON AN "AS IS"
 * BASIS, AND BROWN UNIVERSITY HAS NO OBLIGATION TO PROVIDE MAINTENANCE,
 * SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
 */

/*
Portions copyright (c) 2012 Eric Lasota

    This library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Library General Public
    License as published by the Free Software Foundation; either
    version 2 of the License, or (at your option) any later version.

    This library is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    Library General Public License for more details.

    You should have received a copy of the GNU Library General Public
    License along with this library; if not, write to the Free
    Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/*
   Changes to make the code reentrant:
      deglobalize curVidStream
   Additional changes:
      none
   -lsh@cs.brown.edu (Loring Holden)
*/

using System;
using System.Collections.Generic;

using System.Text;

namespace MPEGnet
{
    public partial class VidStream
    {
        /*
         *--------------------------------------------------------------
         *
         * ComputeVector --
         *
         *	Computes motion vector given parameters previously parsed
         *      and reconstructed.
         *
         * Results:
         *      Reconstructed motion vector info is put into recon_* parameters
         *      passed to this function. Also updated previous motion vector
         *      information.
         *
         * Side effects:
         *      None.
         *
         *--------------------------------------------------------------
         */

        void ComputeVector(ref int recon_right_ptr, ref int recon_down_ptr, ref int recon_right_prev, ref int recon_down_prev,
            int f, bool full_pel_vector, int motion_h_code, int motion_v_code, int motion_h_r, int motion_v_r)
        {
            int comp_h_r, comp_v_r;
            int right_little, right_big, down_little, down_big;
            int max, min, new_vector;

            /* The following procedure for the reconstruction of motion vectors 	
               is a direct and simple implementation of the instructions given	
               in the mpeg December 1991 standard draft. 				
             */

            if (f == 1 || motion_h_code == 0)
                comp_h_r = 0;
            else
                comp_h_r = f - 1 - motion_h_r;

            if (f == 1 || motion_v_code == 0)
                comp_v_r = 0;
            else
                comp_v_r = f - 1 - motion_v_r;

            right_little = motion_h_code * f;
            if (right_little == 0)
                right_big = 0;
            else
            {
                if (right_little > 0)
                {
                    right_little = right_little - comp_h_r;
                    right_big = right_little - 32 * f;
                }
                else
                {
                    right_little = right_little + comp_h_r;
                    right_big = right_little + 32 * f;
                }
            }

            down_little = motion_v_code * f;
            if (down_little == 0)
                down_big = 0;
            else
            {
                if (down_little > 0)
                {
                    down_little = down_little - comp_v_r;
                    down_big = down_little - 32 * f;
                }
                else
                {
                    down_little = down_little + comp_v_r;
                    down_big = down_little + 32 * f;
                }
            }

            max = 16 * f - 1;
            min = -16 * f;

            new_vector = recon_right_prev + right_little;

            if (new_vector <= max && new_vector >= min)
                recon_right_ptr = recon_right_prev + right_little;
            /* just new_vector */
            else
                recon_right_ptr = recon_right_prev + right_big;
            recon_right_prev = recon_right_ptr;
            if (full_pel_vector)
                recon_right_ptr = recon_right_ptr << 1;

            new_vector = recon_down_prev + down_little;
            if (new_vector <= max && new_vector >= min)
                recon_down_ptr = recon_down_prev + down_little;
            /* just new_vector */
            else
                recon_down_ptr = recon_down_prev + down_big;
            recon_down_prev = recon_down_ptr;
            if (full_pel_vector)
                recon_down_ptr = recon_down_ptr << 1;
        }


        /*
         *--------------------------------------------------------------
         *
         * ComputeForwVector --
         *
         *	Computes forward motion vector by calling ComputeVector
         *      with appropriate parameters.
         *
         * Results:
         *	Reconstructed motion vector placed in recon_right_for_ptr and
         *      recon_down_for_ptr.
         *
         * Side effects:
         *      None.
         *
         *--------------------------------------------------------------
         */

        void ComputeForwVector( ref int recon_right_for_ptr, ref int recon_down_for_ptr )
        {
            ComputeVector(ref recon_right_for_ptr, ref recon_down_for_ptr,
		        ref mblock.recon_right_for_prev, 
		        ref mblock.recon_down_for_prev,
		        (int) picture.forw_f,
		        picture.full_pel_forw_vector,
		        mblock.motion_h_forw_code, mblock.motion_v_forw_code,
		        (int)mblock.motion_h_forw_r, (int)mblock.motion_v_forw_r); 
        }


        /*
         *--------------------------------------------------------------
         *
         * ComputeBackVector --
         *
         *	Computes backward motion vector by calling ComputeVector
         *      with appropriate parameters.
         *
         * Results:
         *	Reconstructed motion vector placed in recon_right_back_ptr and
         *      recon_down_back_ptr.
         *
         * Side effects:
         *      None.
         *
         *--------------------------------------------------------------
         */

        void ComputeBackVector( ref int recon_right_back_ptr, ref int recon_down_back_ptr )
        {
            ComputeVector(ref recon_right_back_ptr, ref recon_down_back_ptr,
                ref mblock.recon_right_back_prev, 
                ref mblock.recon_down_back_prev,
                (int) picture.back_f, 
                picture.full_pel_back_vector,
                mblock.motion_h_back_code, mblock.motion_v_back_code,
                (int)mblock.motion_h_back_r, (int)mblock.motion_v_back_r); 

        }

    }
}
